﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Office.Core;
using System.Data;
using PowerPoint = Microsoft.Office.Interop.PowerPoint;

namespace EmbeddedLinkUpdater.Code.Documents
{
    public class PowerPointDocument : Document
    {
        public PowerPointDocument(string fileName) : base(fileName)
        {
        }

        public override void UpdateDocumentLinks(DataSet linksToReplace)
        {
            AnalyzeOrUpdateLinks(linksToReplace, true);
        }

        public override List<string> AnalyzeLinks()
        {
            AnalyzeOrUpdateLinks(null, false);

            return DocumentLinks;
        }

        private void AnalyzeOrUpdateLinks(DataSet linksToReplace, bool update)
        {
            PowerPoint.Application powerPointApplication = null;
   
            try
            {
                powerPointApplication = new PowerPoint.Application();
                powerPointApplication.AutomationSecurity = Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityForceDisable;
         
                if (FileInUse(FileName))
                    throw new ApplicationException("Failed to update. File in use.");

                var document = powerPointApplication.Presentations.Open(FileName, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);

                foreach (PowerPoint.Hyperlink link in from PowerPoint.Slide slide in document.Slides from PowerPoint.Hyperlink link in slide.Hyperlinks select link)
                {
                    if (update && linksToReplace != null)
                    {
                        var tableLinksToReplace = linksToReplace.Tables[0];
                        foreach (DataRow row in tableLinksToReplace.Rows)
                        {
                            if (link.Address != null)
                                link.Address = link.Address.ReplaceIgnoreCase(row["OldLink"].ToString(), row["NewLink"].ToString());

                            if (!String.IsNullOrEmpty(link.TextToDisplay))
                                link.TextToDisplay = link.TextToDisplay.ReplaceIgnoreCase(row["OldLink"].ToString(), row["NewLink"].ToString());
                        }
                    }
                    else
                    {
                        DocumentLinks.Add(link.Address);
                    }
                    Marshal.ReleaseComObject(link);
                }

                if(update) document.Save();
                document.Close();
                Marshal.ReleaseComObject(document);
            }
            catch (ApplicationException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Failed to update document links", ex);
            }
            finally
            {
                if (powerPointApplication != null)
                {
                    powerPointApplication.Quit();
                    Marshal.ReleaseComObject(powerPointApplication);
                }

                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }
    }
}
